using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Q.Framework.Extension
{
    public static class StringExtension
    {
        public enum TypeMask { Cpf, Cnpj, CpfOrCnpj, Telefone, Cep, Placa }

        public static String Mask(this String value, TypeMask typeMask)
        {
            if (value == null)
                return value;

            MaskedTextProvider mask = null;
            value = value.Trim();

            switch (typeMask)
            {
                case TypeMask.Cnpj:
                    mask = new MaskedTextProvider("00,000,000/0000-00");
                    mask.Set(value.Trim());
                    value = mask.ToString();
                    break;
                case TypeMask.Cpf:
                    mask = new MaskedTextProvider("000,000,000-00");
                    mask.Set(value.Trim());
                    value = mask.ToString();
                    break;
                case TypeMask.Cep:
                    mask = new MaskedTextProvider("00000-000");
                    mask.Set(value.Trim());
                    value = mask.ToString();
                    break;
                case TypeMask.Telefone:
                    mask = new MaskedTextProvider("(00) 0000-0000");
                    mask.Set(value.Trim().Replace(" ", ""));
                    value = mask.ToString();
                    break;
                case TypeMask.CpfOrCnpj:
                    mask = new MaskedTextProvider(value.Trim().Length > 11 ? "00,000,000/0000-00" : "000,000,000-00");
                    mask.Set(value.Trim());
                    value = mask.ToString();
                    break;
                case TypeMask.Placa:
                    mask = new MaskedTextProvider("AAA-0000");
                    mask.Set(value.Trim());
                    value = mask.ToString();
                    break;
            }

            return value;
        }

        public static String RemoveMask(this String value)
        {
            return value.Replace("/", "").
                         Replace(".", "").
                         Replace(";", "").
                         Replace("(", "").
                         Replace(")", "").
                         Replace("-", "").
                         Replace("<", "").
                         Replace(">", "").
                         Replace(":", "").
                         Replace("_", "");
        }

        public static Boolean IsNullOrWhiteSpace(this String value)
        {
            return String.IsNullOrWhiteSpace(value);
        }

        /// <summary>
        /// Realiza a conversão do tipo String para qualquer tipo que Implementa IConvertible 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T ConvertTo<T>(this String value) where T : IConvertible
        {
            return (T)Convert.ChangeType(value, typeof(T));
        }

        public static object ConvertTo(this String value, Type type)
        {
            if (!typeof(IConvertible).IsAssignableFrom(type))
                throw new ArgumentException("Tipo não implementa a interface IConvertible", "type");

            if (type == typeof(String))
                return value;

            return Convert.ChangeType(value, type);
        }

        public static Decimal ToDecimal(this String value)
        {
            return ToDecimal(value, false);
        }

        public static Decimal ToDecimal(this String value, Boolean useTryParse)
        {
            Decimal result = 0;
            if (useTryParse)
                Decimal.TryParse(value, out result);
            else
                result = Decimal.Parse(value);

            return result;
        }

        public static Int32 ToInt32(this String value)
        {
            return ToInt32(value, false);
        }

        public static Int32 ToInt32(this String value, Boolean useTryParse)
        {
            Int32 result = 0;
            if (useTryParse)
                Int32.TryParse(value, out result);
            else
                result = Int32.Parse(value);

            return result;
        }

        /// <summary>
        ///  Converts the string representation of a number to its 32-bit signed integer
        ///     equivalent. A return value indicates whether the conversion succeeded.
        /// </summary>
        /// <param name="s">
        /// s:
        ///     A string containing a number to convert.</param>
        /// <returns>true if s was converted successfully; otherwise, false.</returns>
        public static Boolean TryParseToInt(this String s)
        {
            Int32 number;
            return Int32.TryParse(s, out number);
        }

        /// <summary>
        ///     Converts the string representation of a number to its System.Decimal equivalent.
        ///     A return value indicates whether the conversion succeeded or failed.
        /// </summary>
        /// <param name="s">
        /// s:
        ///     The string representation of the number to convert.</param>
        /// <returns>true if s was converted successfully; otherwise, false.</returns>
        public static Boolean TryParseToDecimal(this String s)
        {
            Decimal number;
            return Decimal.TryParse(s, out number);
        }

        public static Boolean TryParse(this String value, Type type, out object result)
        {
            try
            {
                result = System.Convert.ChangeType(value, type);
                return true;
            }
            catch (OverflowException) { throw; }
            catch (Exception)
            {
                result = null;
                return false;
            }
        }

        public static object Parse(this String value, Type type)
        {
            object t = null;
            TryParse(value, type, out t);

            return t;
        }

        public static Boolean TryParse<T>(this String value, out T result) where T : IConvertible
        {
            try
            {
                result = (T)System.Convert.ChangeType(value, typeof(T));
                return true;
            }
            catch (OverflowException) { throw; }
            catch (Exception)
            {
                result = default(T);
                return false;
            }
        }

        public static T Parse<T>(this String value) where T : IConvertible, new()
        {
            T t = new T();
            TryParse(value, out t);

            return t;
        }
    }
}